package org.ehe.business.supplier.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.ehe.business.engineer.domain.vo.EngineerEntityVO;
import org.ehe.business.supplier.domain.SupplierCategoryRelation;
import org.ehe.business.supplier.domain.SupplierInfo;
import org.ehe.business.supplier.domain.bo.SupplierInfoBO;
import org.ehe.business.supplier.domain.dto.CreateSupplierRequest;
import org.ehe.business.supplier.domain.dto.SupplierQueryRequest;
import org.ehe.business.supplier.domain.dto.UpdateSupplierRequest;
import org.ehe.business.supplier.domain.vo.SupplierCategoryVO;
import org.ehe.business.supplier.domain.vo.SupplierInfoVO;
import org.ehe.business.supplier.mapper.SupplierCategoryRelationMapper;
import org.ehe.business.supplier.mapper.SupplierInfoMapper;
import org.ehe.business.supplier.service.SupplierCategoryRelationService;
import org.ehe.business.supplier.service.SupplierCategoryService;
import org.ehe.business.supplier.service.SupplierInfoService;
import org.ehe.common.core.enums.CommonStatusEnum;
import org.ehe.common.core.exception.ServiceException;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author :zhangnn
 * @className :SupplierInfoServiceImpl
 * @description: TODO
 * @date 2025-07-23 10:12:40
 */
@Service
@RequiredArgsConstructor
public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, SupplierInfo> implements SupplierInfoService {

    private final SupplierCategoryRelationMapper categoryRelationMapper;
    private final SupplierCategoryService categoryService;

    // 前缀标识（Supplier的缩写）
    private static final String PREFIX = "SP";
    // 日期格式（年月日）
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
    // 随机数生成器
    private static final Random RANDOM = new Random();
    // 序列号（用于同一毫秒内的重复处理）
    private static int sequence = 0;
    // 序列号最大值（2位：00-99）
    private static final int MAX_SEQUENCE = 99;
    // 锁对象（保证多线程安全）
    private static final ReentrantLock LOCK = new ReentrantLock();

    /**
     * 获取供应商列表信息
     *
     * @param
     * @return
     */
    @Override
    public TableDataInfo<SupplierInfoVO> getAllSuppliers(SupplierInfoBO engineerBO, PageQuery query) {
        // 构建查询条件
        LambdaQueryWrapper<SupplierInfo> lqw = new LambdaQueryWrapper<SupplierInfo>()
            .like(StringUtils.isNotBlank(engineerBO.getSupplierCode()), SupplierInfo::getSupplierCode, engineerBO.getSupplierCode())
            .like(StringUtils.isNotBlank(engineerBO.getSupplierName()), SupplierInfo::getSupplierName, engineerBO.getSupplierName())
            .eq(StringUtils.isNotBlank(engineerBO.getSocialCreditCode()), SupplierInfo::getSocialCreditCode, engineerBO.getSocialCreditCode())
            .eq(engineerBO.getSupplierStatus() != null,SupplierInfo::getSupplierStatus,engineerBO.getSupplierStatus())
            .like(StringUtils.isNotBlank(engineerBO.getContactPerson()), SupplierInfo::getContactPerson, engineerBO.getContactPerson())
            //.like(StringUtils.isNotBlank(engineerBO.getProductCategory()),SupplierInfo::getProductCategory,engineerBO.getProductCategory())
            .eq(SupplierInfo::getTenantId, LoginHelper.getTenantId())
            .orderByDesc(SupplierInfo::getCreateTime);

        //engineerBO.setTenantId(LoginHelper.getTenantId());
        Long categoryId = engineerBO.getCategoryId();
        if (categoryId != null) {
            // 子查询：存在供应商分类关联记录，且分类ID匹配
            lqw.exists("SELECT 1 FROM t_supplier_category_relation scr " +
                "WHERE scr.supplier_id = t_supplier_info.id " +
                "AND scr.category_id = " + categoryId);
        }

        Page<SupplierInfoVO> list = this.baseMapper.selectVoPage(query.build(), lqw);
        list.getRecords().forEach(s ->{
            List<Long> categoryIds = categoryRelationMapper.selectList(new LambdaQueryWrapper<SupplierCategoryRelation>()
                    .eq(SupplierCategoryRelation::getSupplierId,s.getId()))
                .stream().map(SupplierCategoryRelation::getCategoryId).
                collect(Collectors.toList());

            List<SupplierCategoryVO> categoryVOS = categoryService.getCategoriesByIds(categoryIds);
            s.setCategories(categoryVOS);
        });
        return TableDataInfo.build(list);
    }

    /**
     * 获取供应商详情
     *
     * @param id
     * @return
     */
    @Override
    public SupplierInfoVO getSupplierDetail(Long id) {
        SupplierInfo supplierInfo = this.getById(id);
        if (supplierInfo == null) {
            throw new ServiceException("供应商不存在");
        }
        return convertToVO(supplierInfo);
    }

    /**
     * 新增供应商
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int createSupplier(CreateSupplierRequest request) {
        // 校验供应商编码唯一性
//        if (existsBySupplierCode(request.getSupplierCode(), null)) {
//            throw new ServiceException("供应商编码已存在");
//        }
        //生成供应商唯一编码
        request.setSupplierCode(generateCode());

        // 校验社会信用代码唯一性
        if (StringUtils.isNotBlank(request.getSocialCreditCode()) &&
            existsBySocialCreditCode(request.getSocialCreditCode(), null)) {
            throw new ServiceException("社会信用代码已存在");
        }

        // 转换DTO到实体
        SupplierInfo supplierInfo = new SupplierInfo();
        BeanUtil.copyProperties(request, supplierInfo);

        // 设置默认值
        supplierInfo.setSupplierStatus(request.getSupplierStatus() != null ? request.getSupplierStatus() : 1);
        supplierInfo.setIsOcrVerified(0);
        supplierInfo.setVersion(1);
        // 保存供应商信息
        int i = this.baseMapper.insert(supplierInfo);

        // 保存分类关联
        if (i > 0 && CollUtil.isNotEmpty(request.getCategoryIds())) {
            saveCategoryRelations(supplierInfo.getId(), request.getCategoryIds());
        }

        return i;
    }

    /**
     * 保存分类关联
     *
     * @param id
     * @param categoryIds
     */
    private void saveCategoryRelations(Long id,List<Long> categoryIds) {
        if (CollUtil.isEmpty(categoryIds)) {
            return;
        }

        List<SupplierCategoryRelation> relations = categoryIds.stream()
            .map(categoryId -> {
                SupplierCategoryRelation relation = new SupplierCategoryRelation();
                relation.setSupplierId(id);
                relation.setCategoryId(Long.valueOf(categoryId));
                relation.setTenantId(LoginHelper.getTenantId());
                return relation;
            })
            .collect(Collectors.toList());

        relations.forEach(categoryRelationMapper::insert);
    }

    /**
     * 修改供应商
     *
     * @param request
     * @return
     */
    @Override
    public int updateSupplier(UpdateSupplierRequest request) {
        // 检查供应商是否存在
        SupplierInfo existingSupplier = this.getById(request.getId());
        if (existingSupplier == null) {
            throw new ServiceException("供应商不存在");
        }

        // 校验社会信用代码唯一性
        if (StringUtils.isNotBlank(request.getSocialCreditCode()) &&
            existsBySocialCreditCode(request.getSocialCreditCode(), request.getId())) {
            throw new ServiceException("社会信用代码已存在");
        }

        // 转换DTO到实体
        SupplierInfo supplierInfo = new SupplierInfo();
        BeanUtil.copyProperties(request, supplierInfo);

        // 更新分类关联
        if (request.getCategoryIds() != null) {
            updateSupplierCategories(request.getId(), request.getCategoryIds());
        }

        // 更新供应商信息
        int updateResult = this.baseMapper.updateById(supplierInfo);
        return updateResult;
    }

    /**
     * 删除供应商
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteSupplier(Long id) {
        SupplierInfo supplier = this.getById(id);
        if (supplier == null) {
            throw new ServiceException("供应商不存在");
        }

        // 删除分类关联
        categoryRelationMapper.delete(
            new LambdaQueryWrapper<SupplierCategoryRelation>()
                .eq(SupplierCategoryRelation::getSupplierId, id)
                .eq(SupplierCategoryRelation::getTenantId, LoginHelper.getTenantId())
        );

        // 删除供应商
        return this.removeById(id);
    }

    /**
     * 批量删除供应商
     *
     * @param ids
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteSuppliers(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return true;
        }

        // 删除分类关联
        categoryRelationMapper.delete(
            new LambdaQueryWrapper<SupplierCategoryRelation>()
                .in(SupplierCategoryRelation::getSupplierId, ids)
                .eq(SupplierCategoryRelation::getTenantId, LoginHelper.getTenantId())
        );

        // 批量删除供应商
        return this.removeByIds(ids);
    }

    @Override
    public boolean updateSupplierStatus(Long id, Integer status) {
        return this.update(
            new LambdaUpdateWrapper<SupplierInfo>()
                .eq(SupplierInfo::getId, id)
                .eq(SupplierInfo::getTenantId, LoginHelper.getTenantId())
                .set(SupplierInfo::getSupplierStatus, status)
        );
    }


    /**
     * 获取供应商分类信息
     *
     * @param id
     * @return
     */
    @Override
    public List<Long> getSupplierCategories(Long id) {
        return categoryRelationMapper.selectList(
            new LambdaQueryWrapper<SupplierCategoryRelation>()
                .eq(SupplierCategoryRelation::getSupplierId, id)
                .eq(SupplierCategoryRelation::getTenantId, LoginHelper.getTenantId())
        ).stream().map(SupplierCategoryRelation::getCategoryId).collect(Collectors.toList());
    }

    /**
     * 更新供应商关联信息
     *
     * @param id
     * @param categoryIds
     * @return
     */
    @Override
    public int updateSupplierCategories(Long id, List<Long> categoryIds) {
        //删除原有分类关系
        categoryRelationMapper.delete(new QueryWrapper<SupplierCategoryRelation>().eq("supplier_id",id));
        categoryIds.forEach(c->{
            SupplierCategoryRelation relation = new SupplierCategoryRelation();
            relation.setCategoryId(c);
            relation.setSupplierId(id);
            relation.setTenantId(LoginHelper.getTenantId());
            relation.setCreateBy(LoginHelper.getUsername());
            categoryRelationMapper.insert(relation);
        });
        return 0;
    }


    /**
     * 转换实体到VO
     */
    private SupplierInfoVO convertToVO(SupplierInfo supplierInfo) {
        if (supplierInfo == null) {
            return null;
        }

        SupplierInfoVO vo = new SupplierInfoVO();
        BeanUtil.copyProperties(supplierInfo, vo);

        // 设置状态描述
        vo.setSupplierStatusDesc(supplierInfo.getSupplierStatus() == 1 ? "启用" : "停用");
        vo.setOcrVerifiedDesc(supplierInfo.getIsOcrVerified() == 1 ? "已验证" : "未验证");

        // 计算合作天数
        if (supplierInfo.getCooperationStartDate() != null) {
            long cooperationDays = ChronoUnit.DAYS.between(supplierInfo.getCooperationStartDate(), LocalDate.now());
            vo.setCooperationDays(cooperationDays);
            vo.setIsNewSupplier(cooperationDays < 30);
        }

        // 设置分类信息
        List<Long> categoryIds = getSupplierCategories(supplierInfo.getId());
        vo.setCategoryIds(categoryIds);

        if (CollUtil.isNotEmpty(categoryIds)) {
            List<SupplierCategoryVO> categories = categoryService.getCategoriesByIds(categoryIds);
            vo.setCategories(categories);

            String categoryNames = categories.stream()
                .map(SupplierCategoryVO::getCategoryName)
                .collect(Collectors.joining(","));
            vo.setCategoryNames(categoryNames);
        }

        return vo;
    }

    /**
     * 校验供应商编码唯一性
     *
     * @param supplierCode
     * @param excludeId
     * @return
     */
    @Override
    public boolean existsBySupplierCode(String supplierCode, Long excludeId) {
        LambdaQueryWrapper<SupplierInfo> queryWrapper = new LambdaQueryWrapper<SupplierInfo>()
            .eq(SupplierInfo::getSupplierCode, supplierCode)
            .eq(SupplierInfo::getTenantId, LoginHelper.getTenantId());

        if (excludeId != null) {
            queryWrapper.ne(SupplierInfo::getId, excludeId);
        }

        return this.count(queryWrapper) > 0;
    }

    /**
     * 校验社会信用代码
     *
     * @param socialCreditCode
     * @param excludeId
     * @return
     */
    @Override
    public boolean existsBySocialCreditCode(String socialCreditCode, Long excludeId) {
        LambdaQueryWrapper<SupplierInfo> queryWrapper = new LambdaQueryWrapper<SupplierInfo>()
            .eq(SupplierInfo::getSocialCreditCode, socialCreditCode)
            .eq(SupplierInfo::getTenantId, LoginHelper.getTenantId());

        if (excludeId != null) {
            queryWrapper.ne(SupplierInfo::getId, excludeId);
        }

        return this.count(queryWrapper) > 0;
    }


    /**
     * 生成供应商唯一编码
     *
     * @return 唯一编码字符串
     */
    private String generateCode() {
        try {
            LOCK.lock();

            // 1. 生成日期部分（8位：yyyyMMdd）
            String datePart = DATE_FORMAT.format(new Date());

            // 2. 生成随机数部分（4位：0000-9999）
            int randomNum = RANDOM.nextInt(10000);
            String randomPart = String.format("%04d", randomNum);

            // 3. 生成序列号部分（2位：00-99，循环递增）
            String sequencePart = String.format("%02d", sequence);
            sequence = (sequence + 1) % (MAX_SEQUENCE + 1);

            // 4. 拼接所有部分
            return PREFIX + datePart + randomPart + sequencePart;
        } finally {
            LOCK.unlock();
        }
    }

    /**
     * 供应商校验
     * @param supplierId
     */
    @Override
    public SupplierInfoVO validateSupplier(Long supplierId) {
        SupplierInfoVO supplier = this.baseMapper.selectVoById(supplierId);
        if (supplier == null) {
            //todo 异常信息封装处理
            throw new ServiceException("供应商不存在");        }
        if (CommonStatusEnum.isDisable(supplier.getSupplierStatus())) {
            //todo 异常信息封装处理
            throw new ServiceException("供应商({"+supplier.getSupplierName()+"})未启用");        }
        return supplier;
    }
}
